﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using AvalonDock;
using Caliburn.PresentationFramework.Views;

namespace MTGenome.UI
{
    public class DockableContentEx : DockableContent
    {
        #region ViewModel

        /// <summary>
        /// ViewModel Dependency Property
        /// </summary>
        public static readonly DependencyProperty ViewModelProperty =
            DependencyProperty.Register("ViewModel", typeof(object), typeof(DockableContentEx),
                new FrameworkPropertyMetadata((object)null,
                    new PropertyChangedCallback(OnViewModelChanged)));

        /// <summary>
        /// Gets or sets the ViewModel property.  This dependency property 
        /// indicates the ViewModel of this View, used to workaround binding issues with AvalonDock.
        /// </summary>
        public object ViewModel
        {
            get { return (object)GetValue(ViewModelProperty); }
            set { SetValue(ViewModelProperty, value); }
        }

        /// <summary>
        /// Handles changes to the ViewModel property.
        /// </summary>
        private static void OnViewModelChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ((DockableContentEx)d).OnViewModelChanged(e);
        }

        /// <summary>
        /// Provides derived classes an opportunity to handle changes to the ViewModel property.
        /// </summary>
        protected virtual void OnViewModelChanged(DependencyPropertyChangedEventArgs e)
        {
            if (e.NewValue != null && State != DockableContentState.Document)
            {
                View.SetModel(this, e.NewValue);
            }
        }

        #endregion

        #region IsShown

        /// <summary>
        /// IsShown Dependency Property
        /// </summary>
        public static readonly DependencyProperty IsShownProperty =
            DependencyProperty.Register("IsShown", typeof(bool), typeof(DockableContentEx),
                new FrameworkPropertyMetadata((bool)false, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
                    new PropertyChangedCallback(OnIsShownChanged)));

        /// <summary>
        /// Gets or sets the IsShown property.  This dependency property 
        /// indicates if the control is shown.
        /// </summary>
        public bool IsShown
        {
            get { return (bool)GetValue(IsShownProperty); }
            set { SetValue(IsShownProperty, value); }
        }

        /// <summary>
        /// Handles changes to the IsShown property.
        /// </summary>
        private static void OnIsShownChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ((DockableContentEx)d).OnIsShownChanged(e);
        }

        /// <summary>
        /// Provides derived classes an opportunity to handle changes to the IsShown property.
        /// </summary>
        protected virtual void OnIsShownChanged(DependencyPropertyChangedEventArgs e)
        {
            if ((bool)e.NewValue && (State == DockableContentState.Hidden))
                Show();
            if ((bool)e.OldValue && (State != DockableContentState.Hidden))
                Hide();
        }

        #endregion

        public DockableContentEx()
        {
            //Loaded += (sender, e) => PropertyChanged
        }

        protected override void OnStateChanged(DockableContentState oldState, DockableContentState newState)
        {
            // If the new state is Document, we need to remove the ViewModel.  The reason is, Caliburn's ViewModelBinder will
            // set the view as a child of the ContentPresenter of the tab control.  This will cause WPF to remove it from the 
            // DockableContent's visual tree.  Whenever we switch back to a state other than Document, set the ViewModel back to 
            // this view.

            IsShown = newState != DockableContentState.Hidden;

            if (newState == DockableContentState.Document)
            {
                object content = Content;
                View.SetModel(this, null);
                Content = content;
            }
            else if (oldState == DockableContentState.Document)
            {
                View.SetModel(this, ViewModel);
            }

            base.OnStateChanged(oldState, newState);
        }
    }
}
